#include <math.h>
#include <stdio.h>

typedef struct Array {
    void* data;
    unsigned long size;
    int sparse;
    const unsigned long* idx;
    unsigned long nnz;
} Array;

struct LangCAtomicFun {
    void* libModel;
    int (*forward)(void* libModel,
                   int atomicIndex,
                   int q,
                   int p,
                   const Array tx[],
                   Array* ty);
    int (*reverse)(void* libModel,
                   int atomicIndex,
                   int p,
                   const Array tx[],
                   Array* px,
                   const Array py[]);
};

void cartpole_dynamics_flow_map_sparse_jacobian(double const *const * in,
                                                double*const * out,
                                                struct LangCAtomicFun atomicFun) {
   //independent variables
   const double* x = in[0];

   //dependent variables
   double* jac = out[0];

   // auxiliary variables
   double v[23];

   v[0] = sin(x[2]);
   v[1] = 0.2 * v[0];
   v[2] = cos(x[2]);
   v[3] = 0.0500074996250188 * v[2];
   v[4] = 2. + v[1] * v[0] + v[3] * v[2];
   jac[5] = 1 / v[4];
   v[5] = 0 - x[4];
   v[6] = 0 - v[5];
   v[7] = -1 * sin(x[2]);
   v[8] = v[7] * x[3];
   v[9] = cos(x[2]);
   v[10] = v[2] * x[3];
   v[11] = 0.2 * (0 - 0.5 * x[4]);
   v[12] = 0.2 * v[10] - v[11];
   v[13] = 0.2 * v[6] * v[10] - x[4] * v[12];
   v[14] = v[9] * x[3];
   v[15] = v[14] * v[11];
   v[16] = v[5] * v[14];
   v[17] = v[0] * x[3];
   v[18] = 0.2 * v[17];
   v[19] = 1.49992500374981 * v[17] * v[11] + 0.0500074996250188 * v[5] * v[17] + x[4] * v[18];
   v[4] = ((- jac[5]) * (v[1] * v[9] + 0.2 * v[9] * v[0] + v[3] * v[7] + 0.0500074996250188 * v[7] * v[2])) / v[4];
   v[3] = x[5] - v[0] * v[13] - v[2] * v[19];
   v[1] = 0.0500074996250188 * (0 - v[0]);
   v[20] = 0.2 * v[2];
   v[21] = v[1] * v[2] + v[20] * v[0];
   v[22] = - v[9];
   jac[2] = jac[5] * (0 - (v[0] * (0.2 * v[6] * v[8] - x[4] * 0.2 * v[8]) + v[9] * v[13]) - (v[2] * (1.49992500374981 * v[15] + 0.0500074996250188 * v[16] + x[4] * 0.2 * v[14]) + v[7] * v[19])) + v[4] * v[3] - 9.81 * (v[21] * v[4] + (v[1] * v[7] + 0.0500074996250188 * v[22] * v[2] + v[20] * v[9] + 0.2 * v[7] * v[0]) * jac[5]);
   v[11] = v[0] * v[11];
   v[5] = v[5] * v[0];
   jac[3] = jac[5] * (0 - v[0] * (0.2 * v[6] * v[2] - x[4] * 0.2 * v[2]) - v[2] * (1.49992500374981 * v[11] + 0.0500074996250188 * v[5] + x[4] * 0.2 * v[0]));
   v[6] = v[17] * -0.1;
   v[17] = -1 * v[17];
   jac[4] = jac[5] * (0 - v[0] * (0.2 * v[10] - (x[4] * 0.1 + v[12])) - v[2] * (1.49992500374981 * v[6] + 0.0500074996250188 * v[17] + v[18]));
   jac[6] = 14.9992500374981 * v[15] - 1.49992500374981 * (9.81 * v[22] + v[2] * jac[2] + v[7] * (jac[5] * v[3] - 9.81 * v[21] * jac[5]) + v[16]);
   jac[7] = 14.9992500374981 * v[11] - 1.49992500374981 * (v[2] * jac[3] + v[5]);
   jac[8] = 14.9992500374981 * v[6] - 1.49992500374981 * (v[2] * jac[4] + v[17]);
   jac[9] = 0 - 1.49992500374981 * v[2] * jac[5];
   // dependent variables without operations
   jac[0] = 1;
   jac[1] = 1;
}

